home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / x / animutil / xanim229.lha / xanim / txtmerge.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-08  |  11.4 KB  |  555 lines

  1.  
  2. /*
  3.  * txtmerge.c
  4.  *
  5.  * Copyright (C) 1990,1991,1992 by Mark Podlipec. 
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified and redistributed
  9.  * without fee provided that this copyright notice is preserved 
  10.  * intact on all copies and modified copies.
  11.  * 
  12.  * There is no warranty or other guarantee of fitness of this software.
  13.  * It is provided solely "as is". The author(s) disclaim(s) all
  14.  * responsibility and liability with respect to this software's usage
  15.  * or its effect upon hardware or computer systems.
  16.  *
  17.  */
  18.  /*
  19.   * Description:
  20.   *
  21.   * This program reads a txt91(see XAnim docs) file and merges the listed
  22.   * gif files into one gif file. 
  23.   *
  24.   * Eventually, I'd like to have this program compare the current image
  25.   * with the previous image and check to see if only a small section of
  26.   * the screen changed from the previous image. Worth a shot.
  27.   */
  28.  
  29.  /*
  30.   * Rev 1.00    23Jul91    Mark Podlipec
  31.   *    creation
  32.   * Rev 1.01    08Jan92    Mark Podlipec
  33.   *     use all colormaps, not just 1st.
  34.   * 
  35.   */
  36. #define DA_REV 1.01
  37.  
  38. #include <stdio.h>
  39. #include <sys/types.h>
  40. #include "mytypes.h"
  41. #include "xanim.h"
  42. #include "xanim_gif.h"
  43.  
  44. #define MAXVAL  4100            /* maxval of lzw coding size */
  45. #define MAXVALP 4200
  46.  
  47. int debug_flag = 0;  /* make these options */
  48. int verbose = 0;  /* make these options */
  49. int imagex = 0;
  50. int imagey = 0;
  51. int imagec = 0;
  52.  
  53. GIF_Color gif_cmap[256];
  54.  
  55. ULONG GIF_Get_Code();
  56. void GIF_Decompress();
  57. void GIF_Get_Next_Entry();
  58. void GIF_Add_To_Table();
  59. void GIF_Send_Data();
  60. void GIF_Clear_Table();
  61. void GIF_Screen_Header();
  62. void GIF_Image_Header();
  63.  
  64. GIF_Screen_Hdr gifscrn;
  65. GIF_Image_Hdr gifimage;
  66. GIF_Table table[MAXVALP];
  67.  
  68. ULONG root_code_size,code_size,CLEAR,EOI,INCSIZE;
  69. ULONG nextab;
  70. ULONG gif_mask[16] = {1,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,0,0};
  71. ULONG gif_ptwo[16] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,0,0};
  72. UBYTE gif_buff[MAXVALP];
  73. ULONG gif_block_size;
  74. int num_bits,bits;
  75.  
  76. int pic_i;
  77. char gif_file_name[256];
  78. int screen_was_last;
  79.  
  80. void TheEnd()
  81. {
  82.  exit(0);
  83. }
  84.  
  85. void TheEnd1(p)
  86. char *p;
  87. {
  88.  fprintf(stderr,"%s",p);
  89.  TheEnd();
  90. }
  91.  
  92. Usage()
  93. {
  94.   fprintf(stderr,"\nUsage: txtmerge anim.txt91 > anim.gifanim\n\n");
  95.   exit(0);
  96. }
  97.  
  98. main(argc,argv)
  99. int argc;
  100. char *argv[];
  101. {
  102.  FILE *fp;
  103.  int ret,i;
  104.  int num_of_files,num_of_frames;
  105.  
  106.  fprintf(stderr,"txtmerge Rev %2.2f (C) 1991,1992 by Mark Podlipec\n",DA_REV);
  107.  
  108.  if (argc < 2) Usage();
  109.  
  110.  screen_was_last = FALSE;
  111.  i = 1;
  112.  while( i < argc)
  113.  {
  114.   char *p;
  115.   p = argv[i];
  116.   if ( (p[0] == '-') || (p[0] == '+') )
  117.   { 
  118.    switch(p[1])
  119.    {
  120.     case 'v':
  121.             verbose = 1;
  122.             i++;
  123.         break;
  124.     default: 
  125.         Usage();
  126.         exit(0);
  127.         break;
  128.    }
  129.   }
  130.   else break;
  131.  }
  132.  
  133.  if ( (fp=fopen(argv[i],"r"))==0)
  134.  { 
  135.   fprintf(stderr,"Can't open %s for reading.\n",argv[i]); 
  136.   TheEnd();
  137.  }
  138.  
  139.  /* throw away txt91 header 
  140.   */
  141.  fscanf(fp,"%*s",gif_file_name); 
  142.  
  143.  /* read number of files
  144.   */
  145.  fscanf(fp,"%ld",&num_of_files);
  146.  if (num_of_files<=0)
  147.  {
  148.   fprintf(stderr,"num_of_file is wierd=%ld\n",num_of_files);
  149.   fclose(fp);
  150.   TheEnd();
  151.  }
  152.  
  153.  /* Read files, save colormap of 1st one only
  154.   */
  155.  for(i=0;i<num_of_files;i++)
  156.  {
  157.   fscanf(fp,"%s",gif_file_name);
  158.   fprintf(stderr,"Reading %s\n",gif_file_name);
  159.   if (i==0) GIF_Read_File(gif_file_name,1);
  160.   else      GIF_Read_File(gif_file_name,0);
  161.  }
  162.  
  163.  /* Read number of frames if present
  164.   */
  165.  ret=fscanf(fp,"%ld",&num_of_frames);
  166.  if ( (ret==1) && (num_of_frames>=0))
  167.  {
  168.   int action_number;
  169.   int frame;
  170.  
  171.   /* For now throw away frame information.
  172.    * Maybe later incorporation as GIF Chunk(?)
  173.    */
  174.   for(i=0;i<num_of_frames;i++)
  175.   {
  176.    ret = fscanf(fp,"%ld",&frame);
  177.   }
  178.  }
  179.  fputc(';',stdout); /* image separator */
  180.  fclose(fp);
  181. }
  182.  
  183.  
  184. /*
  185.  * Read a GIF file, outputting to fname as we go.
  186.  * It would be faster to read and write the individual blocks,
  187.  * but eventually we'd like to optimize based on changes from
  188.  * previous images(ie only a small section of the image changed.
  189.  */
  190. void GIF_Read_File(fname,first_image)
  191. char *fname;
  192. int first_image;
  193. {
  194.  FILE *fp;
  195.  int ret,i,exit_flag;
  196.  
  197.  if ( (fp=fopen(fname,"r"))==0)
  198.  { 
  199.   fprintf(stderr,"Can't open %s for reading.\n",fname); 
  200.   TheEnd();
  201.  }
  202.  
  203.  GIF_Screen_Header(fp,stdout,first_image);
  204.  
  205.  /*** read until  ,  separator */
  206.  do
  207.  {
  208.   i=fgetc(fp);
  209.   if ( (i<0) && feof(fp))
  210.   {
  211.    fclose(fp);
  212.    TheEnd1("GIF_Read_Header: Unexpected End of File\n");
  213.   }
  214.  } while(i != ',');
  215.  
  216.  fputc(',',stdout); /* image separator */
  217.  
  218.  GIF_Image_Header(fp,stdout,first_image);
  219.  
  220.  /*** Setup ACTION for IMAGE */
  221.  
  222.  GIF_Decompress(fp,stdout,0);
  223.  fputc(0,stdout);  /* block count of zero */
  224.  
  225.  fclose(fp);
  226. }
  227.  
  228. void GIF_Decompress(fp,fout)
  229. FILE *fp,*fout;
  230. {
  231.  register ULONG code,old;
  232.  
  233.  pic_i = 0;
  234.  bits=0;
  235.  num_bits=0;
  236.  gif_block_size=0;
  237.     /* starting code size of LZW */
  238.  root_code_size=(fgetc(fp) & 0xff); fputc(root_code_size,fout);
  239.  GIF_Clear_Table();                /* clear decoding symbol table */
  240.  
  241.  code=GIF_Get_Code(fp,fout);
  242.  
  243.  if (code==CLEAR) 
  244.  {
  245.   GIF_Clear_Table(); 
  246.   code=GIF_Get_Code(fp,fout);
  247.  }
  248.  /* write code(or what it currently stands for) to file */
  249.  GIF_Send_Data(code);   
  250.  old=code;
  251.  code=GIF_Get_Code(fp,fout);
  252.  do
  253.  {
  254.   if (table[code].valid==1)    /* if known code */
  255.   {
  256.        /* send it's associated string to file */
  257.     GIF_Send_Data(code);
  258.     GIF_Get_Next_Entry(fp);       /* get next table entry (nextab) */
  259.     GIF_Add_To_Table(old,code,nextab);  /* add old+code to table */
  260.     old=code;
  261.   }
  262.   else      /* code doesn't exist */
  263.   {
  264.     GIF_Add_To_Table(old,old,code);   /* add old+old to table */
  265.     GIF_Send_Data(code);
  266.     old=code;
  267.   }
  268.   code=GIF_Get_Code(fp,fout);
  269.   if (code==CLEAR)
  270.   { 
  271.    GIF_Clear_Table();
  272.    code=GIF_Get_Code(fp,fout);
  273.    GIF_Send_Data(code);
  274.    old=code;
  275.    code=GIF_Get_Code(fp,fout);
  276.   }
  277.  } while(code!=EOI);
  278. }
  279.  
  280. void GIF_Get_Next_Entry(fp)
  281. FILE *fp;
  282. {
  283.    /* table walk to empty spot */
  284.  while(  (table[nextab].valid==1)
  285.        &&(nextab<MAXVAL)
  286.       ) nextab++;
  287.  /* 
  288.   * Ran out of space??!?  Something's roached 
  289.   */
  290.  if (nextab>=MAXVAL)    
  291.  { 
  292.   fprintf(stderr,"Error: GetNext nextab=%ld\n",nextab);
  293.   fclose(fp);
  294.   TheEnd();
  295.  }
  296.  if (nextab==INCSIZE)   /* go to next table size (and LZW code size ) */
  297.  {
  298.    /* fprintf(stderr,"GetNext INCSIZE was %ld ",nextab); */
  299.    code_size++; INCSIZE=(INCSIZE*2)+1;
  300.    if (code_size>=12) code_size=12;
  301. /*   fprintf(stderr,"<%ld>",INCSIZE); */
  302.  }
  303.  
  304. }
  305. /*  body is associated string
  306.     next is code to add to that string to form associated string for
  307.     index
  308. */     
  309.  
  310. void GIF_Add_To_Table(body,next,index)
  311. register ULONG body,next,index;
  312. {
  313.  if (index>MAXVAL)
  314.  { 
  315.   fprintf(stderr,"Error index=%ld\n",index);
  316.  }
  317.  else
  318.  {
  319.   table[index].valid=1;
  320.   table[index].data=table[next].first;
  321.   table[index].first=table[body].first;
  322.   table[index].last=body;
  323.  }
  324. }
  325.  
  326. void GIF_Send_Data(index)
  327. register int index;
  328. {
  329.  register int i,j;
  330.  i=0;
  331.  do         /* table walk to retrieve string associated with index */
  332.  { 
  333.   gif_buff[i]=table[index].data; 
  334.   i++;
  335.   index=table[index].last;
  336.   if (i>MAXVAL)
  337.   { 
  338.    fprintf(stderr,"Error: Sending i=%ld index=%ld\n",i,index);
  339.    TheEnd();
  340.   }
  341.  } while(index>=0);
  342.  
  343.  /* now invert that string since we retreived it backwards */
  344.  i--;
  345.  for(j=i;j>=0;j--)
  346.  {
  347.   /*pic[pic_i] = gif_buff[j] | gif_pix_offset;*/
  348.   pic_i++;
  349.  }
  350. }
  351.  
  352.  
  353. /* 
  354.  * initialize string table 
  355.  */
  356. void GIF_Init_Table()       
  357. {
  358.  register int maxi,i;
  359.  
  360. if (debug_flag) fprintf(stderr,"Initing Table...");
  361.  maxi=gif_ptwo[root_code_size];
  362.  for(i=0; i<maxi; i++)
  363.  {
  364.   table[i].data=i;   
  365.   table[i].first=i;
  366.   table[i].valid=1;  
  367.   table[i].last = -1;
  368.  }
  369.  CLEAR=maxi; 
  370.  EOI=maxi+1; 
  371.  nextab=maxi+2;
  372.  INCSIZE = (2*maxi)-1;
  373.  code_size=root_code_size+1;
  374. }
  375.  
  376.  
  377. /* 
  378.  * clear table 
  379.  */
  380. void GIF_Clear_Table()   
  381. {
  382.  register int i;
  383. if (debug_flag) fprintf(stderr,"Clearing Table...\n");
  384.  for(i=0;i<MAXVAL;i++) table[i].valid=0;
  385.  GIF_Init_Table();
  386. }
  387.  
  388. /*CODE*/
  389. ULONG GIF_Get_Code(fp,fout) /* get code depending of current LZW code size */
  390. FILE *fp,*fout;
  391. {
  392.  ULONG code;
  393.  register int tmp;
  394.  
  395.  while(num_bits < code_size)
  396.  {
  397.   /**** if at end of a block, start new block */
  398.   if (gif_block_size==0) 
  399.   {
  400.    tmp = fgetc(fp);
  401.    if (tmp >= 0 )
  402.    {
  403.     fputc(tmp,fout);
  404.     gif_block_size=(ULONG)(tmp);
  405.    }
  406.    else TheEnd1("EOF in data stream\n");
  407.   }
  408.  
  409.   tmp = fgetc(fp);   gif_block_size--;
  410.   if (tmp >= 0)
  411.   {
  412.    fputc(tmp,fout);
  413.    bits |= ( ((ULONG)(tmp) & 0xff) << num_bits );
  414.    num_bits+=8;
  415.   }
  416.   else TheEnd1("EOF in data stream\n");
  417.  }
  418.   
  419.  code = bits & gif_mask[code_size];
  420.  bits >>= code_size;
  421.  num_bits -= code_size; 
  422.  
  423.  
  424.  if (code>MAXVAL)
  425.  { 
  426.   fprintf(stderr,"\nError! in stream=%lx \n",code); 
  427.   fprintf(stderr,"CLEAR=%lx INCSIZE=%lx EOI=%lx code_size=%lx \n",
  428.                                            CLEAR,INCSIZE,EOI,code_size); 
  429.   code=EOI;
  430.  }
  431.  
  432.  if (code==INCSIZE)
  433.  {
  434.   if (code_size<12)
  435.   {
  436.    code_size++; INCSIZE=(INCSIZE*2)+1;
  437.   }
  438.   else if (debug_flag) fprintf(stderr,"<13?>"); 
  439.  }
  440.  
  441.  return(code);
  442. }
  443.  
  444.  
  445. /* 
  446.  * read GIF header 
  447.  */
  448. void GIF_Screen_Header(fp,fout,first_time)
  449. FILE *fp,*fout;
  450. int first_time;
  451. {
  452.  int temp,i;
  453.  
  454.  for(i=0;i<6;i++) 
  455.  {
  456.   temp = fgetc(fp);
  457.   if (first_time==TRUE) fputc(temp,fout);
  458.  }
  459.  
  460.  gifscrn.width  = GIF_Get_Short(fp,fout,first_time);
  461.  gifscrn.height = GIF_Get_Short(fp,fout,first_time);
  462.  temp=fgetc(fp);         if (first_time==TRUE) fputc(temp,fout);
  463.  gifscrn.m       =  temp & 0x80;
  464.  gifscrn.cres    = (temp & 0x70) >> 4;
  465.  gifscrn.pixbits =  temp & 0x07;
  466.  gifscrn.bc  = fgetc(fp);     if (first_time==TRUE) fputc(gifscrn.bc,fout);
  467.  temp=fgetc(fp);         if (first_time==TRUE) fputc(temp,fout);
  468.  imagec=gif_ptwo[(1+gifscrn.pixbits)];
  469.  
  470.  if (verbose)
  471.   fprintf(stderr,"Screen: %ldx%ldx%ld m=%ld cres=%ld bkgnd=%ld pix=%ld\n",
  472.     gifscrn.width,gifscrn.height,imagec,gifscrn.m,gifscrn.cres,
  473.     gifscrn.bc,gifscrn.pixbits);
  474.  
  475.  if (gifscrn.m)
  476.  {
  477.   for(i=0;i<imagec;i++)
  478.   {
  479.    gif_cmap[i].cmap.red   = temp = fgetc(fp); 
  480.            if (first_time==TRUE) fputc(temp,fout);
  481.    gif_cmap[i].cmap.green = temp = fgetc(fp); 
  482.            if (first_time==TRUE) fputc(temp,fout);
  483.    gif_cmap[i].cmap.blue  = temp = fgetc(fp); 
  484.            if (first_time==TRUE) fputc(temp,fout);
  485.   }
  486.  }
  487.  screen_was_last = TRUE;
  488. }
  489.  
  490. void GIF_Image_Header(fp,fout,first_time)
  491. FILE *fp,*fout;
  492. int first_time;
  493. {
  494.  int temp,tnum,i;
  495.  
  496.  gifimage.left   = GIF_Get_Short(fp,fout,1);
  497.  gifimage.top    = GIF_Get_Short(fp,fout,1);
  498.  gifimage.width  = GIF_Get_Short(fp,fout,1);
  499.  gifimage.height = GIF_Get_Short(fp,fout,1);
  500.  temp=fgetc(fp); 
  501.  
  502.  gifimage.m        = temp & 0x80;
  503.  gifimage.i        = temp & 0x40;
  504.  gifimage.pixbits  = temp & 0x07;
  505.  
  506.  if (screen_was_last && (first_time==FALSE)) temp |= 0x80;
  507.  temp &= 0xf8;
  508.  temp |= gifscrn.pixbits;
  509.  fputc(temp,fout);
  510.  
  511.  imagex=gifimage.width;
  512.  imagey=gifimage.height;
  513.  tnum=gif_ptwo[(1+gifimage.pixbits)];
  514.  if (verbose)
  515.   fprintf(stderr,"Image: %ldx%ldx%ld m=%ld i=%ld pix=%ld \n",
  516.     imagex,imagey,tnum,gifimage.m,gifimage.i,gifimage.pixbits);
  517.  
  518.  /* if there is an image cmap, then use it */
  519.  if (gifimage.m)
  520.  {
  521.   for(i=0;i<tnum;i++)
  522.   {
  523.    gif_cmap[i].cmap.red   = temp = fgetc(fp); fputc(temp,fout);
  524.    gif_cmap[i].cmap.green = temp = fgetc(fp); fputc(temp,fout);
  525.    gif_cmap[i].cmap.blue  = temp = fgetc(fp); fputc(temp,fout);
  526.   }
  527.  }  /* else if screen was last not 1st time */
  528.  else if (screen_was_last && (first_time==FALSE))
  529.  {
  530.   for(i=0;i<imagec;i++)
  531.   {
  532.    fputc(gif_cmap[i].cmap.red  ,fout);
  533.    fputc(gif_cmap[i].cmap.green,fout);
  534.    fputc(gif_cmap[i].cmap.blue ,fout);
  535.   }
  536.  }
  537.  screen_was_last = FALSE; 
  538. }
  539.  
  540.  
  541. /*
  542.  *
  543.  */
  544. int GIF_Get_Short(fp,fout,first_time)
  545. FILE *fp,*fout;
  546. int first_time;
  547. {
  548.  register int temp,tmp1;
  549.  temp=fgetc(fp);     if (first_time==TRUE) fputc(temp,fout);
  550.  tmp1=fgetc(fp);     if (first_time==TRUE) fputc(tmp1,fout);
  551.  return(temp|( (tmp1) << 8 ));
  552. }
  553.  
  554.  
  555.